
package br.academia.util;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Classe responsável por fazer a formatação de valores para apresentação na
 * visualização.
 *
 */
public class Formatador {

	private static Formatador singleton;

	private SimpleDateFormat df, dfH, dfS, dfE;

	private DecimalFormat dc;

	private DecimalFormat dc1;

	private DecimalFormat dc3;

	private DecimalFormat dc4;

	private DecimalFormat dc5;

	private DecimalFormat dc6;
	
	private DecimalFormat dc7;
	
	private DecimalFormat dc8;

	private SimpleDateFormat horaF;

	public String[] MESES = { "Janeiro", "Fevereiro", "Mar�o", "Abril", "Maio",
			"Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro",
			"Dezembro" };

	public String[] MESES_ABREVIADO = { "Jan.", "Fev.", "Mar.", "Abr.", "Mai.",
			"Jun.", "Jul.", "Ago.", "Set.", "Out.", "Nov.",
			"Dez." };

	private Formatador() {
		df = new SimpleDateFormat("dd/MM/yyyy");
		df.setLenient(false);
		dfH = new SimpleDateFormat("dd/MM/yyyy HH:mm");
		dfE = new SimpleDateFormat("dd 'de' MMMMM 'de' yyyy");
		dfS = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
		dc = new DecimalFormat("#,##0.00");
		dc1 = new DecimalFormat("#,##0.0");
		dc3 = new DecimalFormat("#,##0.000");
		dc4 = new DecimalFormat("#,##0.0000");
		dc5 = new DecimalFormat("####.##");
		dc6 = new DecimalFormat("000,000");
		dc7 = new DecimalFormat("#,##0.00000");
		dc8 = new DecimalFormat("#,##0.000000");
		
		horaF = new SimpleDateFormat("HH:mm");
	}

	public static Formatador getInstance() {
		if (singleton == null) {
			singleton = new Formatador();
		}
		return singleton;
	}

	/** Formata data no formato dd/MM/yyyy*/
	public String formatarData(Date data) {
		return (data == null ? "" : df.format(data));
	}
	
	/** Formata data por extenso */
	public String formatarDataExtenso(Date data) {
		return (data == null ? "" : dfE.format(data));
	}

	public String descreverTempoAnoMesesDias(int qtdDias){
		String descricao = "";
		int anos = qtdDias / 365;
		qtdDias = qtdDias - (anos * 365);
		int meses = qtdDias / 30;
		qtdDias = qtdDias - (meses * 30);

		if (anos > 0) {
			if(meses == 12){
				anos++;
				meses = 0;
			}
			descricao = anos + " ano(s)";
		}

		if (anos > 0 && meses > 0 && qtdDias > 0) {
			descricao = descricao + ", ";

		}else if (anos > 0 && meses > 0) {
			descricao = descricao + " e ";

		}else{
			descricao += " ";
		}

		if (meses > 0) {
			descricao = descricao + meses + " mes(es) ";
		}

		if ((anos > 0 || meses > 0) && qtdDias > 0) {
			descricao = descricao + "e ";
		}

			if (qtdDias > 0) {
				descricao = descricao + qtdDias + " dia(s)";

			}else if(qtdDias == 0){
				if(!(meses > 0 || anos > 0)){
					descricao = "0 dias";
				}
			}

		return descricao;
	}

	/**
	 * Retorna a data contida na String. Caso a data seja inv�lida, � retornado
	 * null
	 *
	 * @param data
	 * @return
	 */
	public Date parseDate(String data) {
		try {
			Date d1 = df.parse(data);
			Date d2 = df.parse("01/01/1900");
			if (d1.before(d2)) {
				return null;
			} else {
				return d1;
			}
		} catch (Exception e) {
			return null;
		}
	}

	public Date parseHora(String hora) {
		try {
			return horaF.parse(hora);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * Retorna String com representação do mÊs informado como argumento. <BR>
	 * 0 - janeiro <br>
	 * 11 - Dezembro
	 *
	 * @param mes
	 *            inteiro representado mÊs.
	 * @return representação do mês.
	 */
	public String formatarMes(int mes) {
		if (mes < 0 || mes > 11)
			throw new IllegalArgumentException("O mês deve estar entre 0 e 11");

		return MESES[mes];
	}

	/**
	 * Retorna String com representação do mês informado como argumento. <BR>
	 * 0 - janeiro <br>
	 * 11 - Dezembro
	 *
	 * @param mes
	 *            inteiro representado mÊs.
	 * @return representação do mês abreviada.
	 */
	public String formatarMesAbreviado(int mes) {
		if (mes < 0 || mes > 11)
			throw new IllegalArgumentException("O mês deve estar entre 0 e 11");

		return MESES_ABREVIADO[mes];
	}

	/**
	 * Sobrecarga de {@see #formatarMes(int)}.
	 *
	 * @param mes
	 *            String com número representando mês
	 * @return representação do mês.
	 *
	 * @see #formatarMes(int)
	 */
	public String formatarMes(String mes) {
		return formatarMes(Integer.parseInt(mes));
	}

	public String formatarMoeda(double valor) {
		return dc.format(valor);
	}

	public String formatarMoeda(Double valor) {
		return dc.format(valor.doubleValue());
	}

	/**
	 * Formata número decimal com uma casa
	 *
	 * @param valor
	 * @return número formatado com uma casa decimal
	 */
	public String formatarDecimal1(double valor) {
		return dc1.format(valor);
	}

	/** Formata Decimal com ,00 opcional, caso o número seja integral */
	public String formatarDecimalInt(double valor) {
		return dc5.format(valor);
	}

	/** Formata números naturais */
	public String formatarNatural(int valor) {
		return dc6.format(valor);
	}

	/** Formata números naturais */
	public String formatarNatural(long valor) {
		return dc6.format(valor);
	}

	// Formata moeda com 3 casas decimais
	public String formatarMoeda3(double valor) {
		return dc3.format(valor);
	}

	public String formatarMoeda3(Double valor) {
		return dc3.format(valor.doubleValue());
	}

	// Formata moeda com 4 casas decimais
	public String formatarMoeda4(double valor) {
		return dc4.format(valor);
	}

	public String formatarMoeda4(Double valor) {
		return dc4.format(valor.doubleValue());
	}
	
	// Formata moeda com 5 casas decimais
	public String formatarMoeda5(double valor) {
		return dc7.format(valor);
	}

	public String formatarMoeda5(Double valor) {
		return dc7.format(valor.doubleValue());
	}
	
	// Formata moeda com 5 casas decimais
	public String formatarMoeda6(double valor) {
		return dc8.format(valor);
	}

	public String formatarMoeda6(Double valor) {
		return dc8.format(valor.doubleValue());
	}

	public String formatarHora(Date data) {
		try {
			return horaF.format(data);
		} catch (Exception e) {
			return null;
		}
	}

	public String formatarDataHora(Date data) {
		return dfH.format(data);
	}

	public String formatarDataHoraSec(Date data) {
		return dfS.format(data);
	}

	public String formatarDataDiaMesAno(Date data) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(data);
		int dia = calendar.get(Calendar.DATE);
		int mes = calendar.get(Calendar.MONTH);
		int ano = calendar.get(Calendar.YEAR);

		return dia + " de " + Formatador.getInstance().formatarMes(mes)
				+ " de " + ano;
	}

	public String formatarDataDia(Date data) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(data);
		int dia = calendar.get(Calendar.DATE);

		return String.valueOf(dia);
	}

	public String formatarCPF_CNPJ(long cpf_cnpj) {

		try {

			StringBuffer id = new StringBuffer(String.valueOf(cpf_cnpj));
			int size = id.length();
			if (id.length() <= 11) {
				// Formata CPF

				if (id.length() < 11) {

					for (int a = id.length(); a < 11; a++) {
						id.insert(0, "0");
					}
				}

				size = id.length();

				id.insert(size - 2, "-");
				id.insert(size - 5, ".");
				id.insert(size - 8, ".");

				return id.toString();

			} else {

				// Formata CNPJ

				return formatarCNPJ(cpf_cnpj);
			}

		} catch (Exception e) {
			return String.valueOf(cpf_cnpj);
		}

	}

	public String formatarCNPJ(long cnpj) {

		try {

			StringBuffer id = new StringBuffer(String.valueOf(cnpj));
			int size = id.length();

			// Formata CNPJ

			if (size < 18) {
				for (int a = size; a < 14; a++) {
					id.insert(0, "0");
				}
			}

			id.insert(12, "-");
			id.insert(8, "/");
			id.insert(5, ".");
			id.insert(2, ".");

			return id.toString();

		} catch (Exception e) {
			return String.valueOf(cnpj);
		}

	}

	public String formatarCodigoUnidade(long codigo) {

		try {
			String value = String.valueOf(codigo);
			String result = "";
			if (value.length() % 2 == 0) {
				for (int a = 0; a <= value.length() - 2; a += 2) {
					result += value.substring(a, a + 2);
					if (a != value.length() - 2) {
						result += ".";
					}
				}
			}
			return result;
		} catch (Exception e) {
			return String.valueOf(codigo);
		}

	}

	/**
	 * Retorna a representa��o em String no formato #####-### do cep passado
	 * como argumento.
	 *
	 * @param cep
	 * @return cep no formato #####-###.
	 */
	public String formatarCep(int cep) {
		try {
			StringBuffer cepSB = new StringBuffer( completaZeros(cep, 8 ));
			cepSB.insert(cepSB.length() - 3, '-');

			return cepSB.toString();
		} catch (Exception e) {
			return String.valueOf(cep);
		}
	}

	
	
	public int parseCep(String cep) {
		try {
			return new Integer(cep.replaceAll("-", ""));
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * Este m�todo retira pontos, tra�o e barras de um CPF ou CNPJ e o
	 * transforma em uma String
	 *
	 * @param req
	 */
	public String parseStringCPFCNPJ(String cpfString) {

		if (cpfString == null)
			return "";

		int tamString = cpfString.length();
		String cpfLimpo = "";

		for (int i = 0; i < tamString; i++) {

			if ((cpfString.charAt(i) != '-') && (cpfString.charAt(i) != '.')
					&& (cpfString.charAt(i) != '/')
					&& (cpfString.charAt(i) != ' ')) {

				cpfLimpo += cpfString.charAt(i);
			}
		}

		return cpfLimpo;
	}

	public String parseRG(String rgString) {
		return parseStringCPFCNPJ(rgString);
	}

	/**
	 * retira "-" de um numero de telefone
	 * @param numero
	 * @return
	 */
	public String parseTelefone(String numero) {
		return parseStringCPFCNPJ(numero);
	}

	/**
	 * insere "-" em um numero de telefone no formato "####-####"
	 * @param numero
	 * @return
	 */
	public String formatarTelefone(int numero) {
		try {
			StringBuffer cepSB = new StringBuffer(String.valueOf(numero));
			cepSB.insert(cepSB.length() - 4, '-');

			return cepSB.toString();
		} catch (Exception e) {
			return String.valueOf(numero);
		}
	}

	public double parseValor(String valor) throws NumberFormatException {
		try {

			if (valor == null)
				return 0.0;

			valor = valor.trim().replaceAll("\\.", "");
			valor = valor.trim().replaceAll(",", ".");

			if ("".equals(valor.trim()))
				return 0.0;

			return Double.parseDouble(valor);
		} catch (Exception e) {
			throw new NumberFormatException();
		}
	}

	/**
	 * Preenche um número com a quantidade de zeros informados
	 *
	 * @param qtd
	 * @param numero
	 * @return
	 */
	public String preencheZeros(int qtd, int numero) {

		StringBuffer buf = new StringBuffer(qtd);
		for (int a = 0; a < qtd; a++) {
			buf.append("0");
		}

		DecimalFormat df = new DecimalFormat(buf.toString());
		return df.format(numero);
	}
	
	/**
	 * Retorna um número mascarado com um certo número de zeros à esquerda
	 * 
	 * @param numero
	 * @param totalZeros
	 * @return
	 */
	public static String completaZeros(long numero, int totalZeros) {
		String zeros = "";
		for (int a = 0; a < totalZeros; a++) {
			zeros += "0";
		}
		DecimalFormat df = new DecimalFormat(zeros);
		return df.format(numero);
	}

	/**
	 * Retorna o nome completo do significado da sigla do
	 * sexo.
	 * @param sexo
	 * @return
	 */
	public String formatarSexo(String sexo) {
		if ("m".equalsIgnoreCase(sexo)) return "Masculino";
		else if ("f".equalsIgnoreCase(sexo)) return "Feminino";
		return null;
	}

	public String formatarBoolean(boolean bool, String tipo) {
		if (bool) {
			if ("V/F".equalsIgnoreCase(tipo)) return "Verdadeiro";
			else if ("S/N".equalsIgnoreCase(tipo)) return "Sim";
		} else {
			if ("V/F".equalsIgnoreCase(tipo)) return "Falso";
			else if ("S/N".equalsIgnoreCase(tipo)) return "N�o";
		}
		return null;
	}

	public String formatarAnoSemestre(Integer inteiro) {
		if (inteiro != null && inteiro > 10000) {
			int ano = inteiro / 10;
			int sem = inteiro - (ano*10);
			return ano + "." + sem;
		}
		return null;
	}
	
	public Date parseDataHoraSec(String dataHora) {
		
		try {
			return dfS.parse(dataHora);
		
		} catch (ParseException e) {
			return null;
		}
	}
}